/** HTA模块 */
var HMod = {
    winSize: function(width, height){},
    /** @returns {HMOD_TABLE_RET} */
    createTable: function(node, cfg){},
    /** @returns {HMOD_XMLHTTP_RET} */
    xmlHttp: function(url, method){},
    writeFile: function(filePath, content, append){},
    readFile: function(filePath){},
    toJsonTC: function(json_str){},
    toJson: function(json_str){},
    timeVar: function(separator, date){},
    clearElement: function(element){}
};

/** 
 * 设置窗口大小，并居中显示
 * @returns {{"W": number, "H": number, "X": number, "Y": number}}
 **/
HMod.winSize = function(width, height){
    var W = width, H = height, X = (window.screen.width - W) / 2, Y = (window.screen.height - H) / 2;
    window.resizeTo(W + 20, H);
    window.moveTo(X, Y);
    HMod["getWinSize"] = {"W": W, "H": H, "X": X, "Y": Y};
    if(document.body){
        document.body.style.width = (W - 0) + "px";
        document.body.style.height = H + "px";
    }
    return HMod["getWinSize"];
}

var HMOD_TABLE_CFG = {
    /** 表头，一行时使用一维数组就行，多行时使用二维数组 */
    thead: [],
    /** 表体，二维数组 */
    tbody: [[]],
    /** 
     * 添加数据回调，回调中的item加入了index和row属性
     * @type {function(item, data): void}
     **/
    addItem: null,
    /** 初始行高 */
    lineHeight: 22,
    /** 表头行高 */
    headLineHeight: null,
    /** 显示序号 */
    Linenum: true,
    /** 序号宽度 */
    linenum_width: 40,
    /** 滚动条默认最大宽度(一般不用改) */
    maxScrollBarWidth: 17,
    /** 线框颜色 */
    lineColor: "#ddd",
    /** 设置滚动条宽度 */
    scrollBarWidth: 0,
    /** 设置每一格宽度的权重 */
    cellWeights: []
};
var HMOD_TABLE_RET = {
    /**
     * 设置数据
     * @param {Array} tbody_data 表体数据（可选）
     * @param {Array} thead_data 表头数据（可选）
     */
    setData: function(tbody_data, thead_data){},
    /**
     * 表头tr标签
     * @type {HTMLElement[]}
     **/
    theadLabels: null,
    /**
     * 表体tr标签
     * @type {HTMLElement[]}
     **/
    tbodyLabels: null
}
/** 
 * 创建一个表格
 * @param {HTMLElement} node 被添加的节点
 * @param {HMOD_TABLE_CFG} cfg 配置项
 * @returns {HMOD_TABLE_RET}
 * @example
 * // 标签
 * <div id="table_content"></div>
 * // 样式
 * #table_content {
 *      width: 100%;
 *      height: 160px;
 *  }
 *  // 脚本
 *  var table_cfg = {
 *      thead: ["head-1", "head-2", "head-3", "head-4"],
 *      tbody:[
 *           ["body-1-1", "body-1-2", "body-1-3", "body-1-4"],
 *           ["body-2-1", "body-2-2", "body-2-3", "body-2-4"],
 *           ["body-3-1", "body-3-2", "body-3-3", "body-3-4"]
 *      ]
 *  };
 *  var table = HMod.createTable(document.getElementById("table_content"), table_cfg);
 *  table.setData();
 * 外部可用类名：
 *  H-mod-table-head        -- 表头的一整条
 *  H-mod-table-body-wrap   -- 表体的滚动容器
 *  H-mod-table-body        -- 表体
 *  H-mod-table-head-cells  -- 表头的每一格
 *  H-mod-table-body-cells  -- 表体的每一格
 *  H-mod-table-com-cell-1  -- 每一行的第一格，后面的数字是格数，从1开始
 *  H-mod-table-head-cell-1 -- 表头第一格，后面的数字是格数，从1开始
 *  H-mod-table-body-cell-1 -- 表体第一格，后面的数字是格数，从1开始
 **/
HMod.createTable = function(node, cfg){
    if(!node.style.overflowX) node.style.overflowX = "hidden";

    var self = {};

    self.width = node.offsetWidth;
    self.height = node.offsetHeight;
    if(!self.width || !self.height){
        return alert("需要设置表格容器的宽高");
    }
    self.theadLabels = [];
    self.tbodyLabels = [];

    cfg.lineColor = cfg.lineColor || HMOD_TABLE_CFG.lineColor;
    cfg.lineHeight = cfg.lineHeight || HMOD_TABLE_CFG.lineHeight;
    cfg.linenum_width = cfg.linenum_width || HMOD_TABLE_CFG.linenum_width;

    self.getCellNums = function(){
        if(typeof cfg.thead[0] === "string") {
            return cfg.thead.length;
        } else if(typeof cfg.thead[0] === "object"){
            return  cfg.thead[0].length;
        } else {
            return 0;
        }
    }

    self.getBlockNums = function(){
        if(typeof cfg.thead[0] === "string") {
            return 1;
        } else if(typeof cfg.thead[0] === "object"){
            return  cfg.thead.length;
        } else {
            return 0;
        }
    }

    /** 根据权重设置宽度 */
    self.cellWidths = function(_width, _cell_num){
        // 获取每一格宽度的权重
        var cellWeights = cfg.cellWeights || HMOD_TABLE_CFG.cellWeights;
        // 获取一行的格子数，这里以表头的格子数为准
        // var cell_num = cfg.thead.length;
        var WeightSum = 0; // 记录权重和
        for (var i = 0; i < _cell_num; i++) WeightSum += cellWeights[i] || 1;

        if(cfg.Linenum)  _width -= cfg.linenum_width;

        var WidthWeightNum = _width / WeightSum;
        var result = [];
        var _sumw = 0;
        for (var i = 0; i < _cell_num; i++) {
            var _w = Math.floor(WidthWeightNum * (cellWeights[i] || 1)); 
            result.push(_w);
            _sumw += _w;
        }
        return result;
    };

    var table_head_wrap = document.createElement("table");
    table_head_wrap.className = "H-mod-table-head"; // 添加类名方便外部修改
    table_head_wrap.style.width = self.width + "px";
    table_head_wrap.style.borderCollapse = "collapse";
    node.appendChild(table_head_wrap);

    self.table_head = document.createElement("thead");
    table_head_wrap.appendChild(self.table_head);

    self.table_body_wrap = document.createElement("div");
    self.table_body_wrap.className = "H-mod-table-body-wrap";
    var table_body_wrap_width = self.width + (cfg.maxScrollBarWidth || HMOD_TABLE_CFG.maxScrollBarWidth) - (cfg.scrollBarWidth || HMOD_TABLE_CFG.scrollBarWidth);
    self.table_body_wrap.style.width = table_body_wrap_width + "px";
    self.table_body_wrap_height = (self.height - cfg.lineHeight - 3);
    if(self.table_body_wrap_height < 0) self.table_body_wrap_height = 0;
    self.table_body_wrap.style.height = self.table_body_wrap_height + "px";
    self.table_body_wrap.style.overflowX = "hidden";
    self.table_body_wrap.style.overflowY = "scroll";
    self.table_body_wrap.style.borderBottom = "1px solid #ddd";
    node.appendChild(self.table_body_wrap);

    var table_table_body = document.createElement("table");
    table_table_body.className = "H-mod-table-body";
    table_table_body.style.width = self.width + "px";
    table_table_body.style.borderCollapse = "collapse";
    table_table_body.style.marginTop = "-1px";
    self.table_body_wrap.appendChild(table_table_body);

    self.table_body = document.createElement("tbody");
    table_table_body.appendChild(self.table_body);

    self.clearElement = function (element) {
        while (element.firstChild) {
            element.removeChild(element.firstChild);
        }
    }

    self.setTHead = function(_thead_data){
        // if(self.table_head && self.table_head.innerHTML) self.table_head.innerHTML = ""; 
        self.clearElement(self.table_head); // 清空表头
        self.theadLabels = []; // 清空表头标签
        var _list;
        if(typeof _thead_data[0] === "string"){
            _list = [_thead_data];
        } else if(typeof _thead_data[0] === "object"){
            _list = _thead_data;
        } else {
            return alert("表头数据格式错误！");
        }

        var cell_num = self.getCellNums();
        var cellWidths = self.cellWidths(self.width, cell_num);
        var lineHeight = cfg.headLineHeight || cfg.lineHeight;

        for(var y = 0; y < _list.length; y++){
            var _lines = _list[y];
            var table_head_tr = document.createElement("tr");
            self.table_head.appendChild(table_head_tr);
            self.theadLabels.push(table_head_tr);
            // 插入序号
            if(cfg.Linenum){
                var _th = document.createElement("th");
                _th.className = "H-mod-table-com-cell-0 H-mod-table-head-cells H-mod-table-head-cell-0";
                _th.style.width = cfg.linenum_width + "px";
                if(y == 0) _th.innerText = "序号";
                _th.style.border = "1px solid #ddd";
                _th.style.height = lineHeight + "px";
                table_head_tr.appendChild(_th);
            }

            for (var x = 0; x < cell_num; x++) {
                var _th = document.createElement("th");
                var c_name_cell = "H-mod-table-com-cell-" + (x + 1);
                var c_name_head = "H-mod-table-head-cell-" + (x + 1);
                _th.className = c_name_cell + " H-mod-table-head-cells " + c_name_head; // 添加类名方便外部修改
                var _th_w = cellWidths[x];
                if(_th_w) _th.style.width = _th_w + "px";
                _th.innerHTML = _lines[x] || "-";
                _th.style.border = "1px solid #ddd";
                _th.style.height = lineHeight + "px";
                table_head_tr.appendChild(_th);
            }
        }
    }

    self.setTBody = function(_tbody_data){
        self.clearElement(self.table_body); // 清空表体
        self.tbodyLabels = [];
        var cell_num = self.getCellNums();
        var cellWidths = self.cellWidths(self.width, cell_num);
        var lineHeight = cfg.lineHeight;
        var wrap_height = Math.min(self.table_body_wrap_height, lineHeight * _tbody_data.length + _tbody_data.length);
        var block_num = self.getBlockNums() - 1;
        if(block_num > 0) wrap_height = wrap_height - (block_num * lineHeight) - 3;
        if(wrap_height < 0) wrap_height = 0;

        self.table_body_wrap.style.height = wrap_height + "px";

        for(var y = 0; y < _tbody_data.length; y++){
            var lines = _tbody_data[y] || [];
            var _tr = document.createElement("tr");
            self.table_body.appendChild(_tr);
            self.tbodyLabels.push(_tr);
            // 插入序号
            if(cfg.Linenum){
                var _td = document.createElement("td");
                _td.className = "H-mod-table-com-cell-0 H-mod-table-body-cells H-mod-table-body-cell-0";
                _td.style.width = cfg.linenum_width + "px";
                _td.style.border = "1px solid #ddd";
                _td.style.height = lineHeight + "px";
                _td.style.textAlign = "center";
                _td.innerText = y + 1;
                _tr.appendChild(_td);
            }
            for (var x = 0; x < cell_num; x++) {
                var _td = document.createElement("td");
                _td.index = x;
                _td.row = y + 1;
                var c_name_cell = "H-mod-table-com-cell-" + (x + 1);
                var c_name_body = "H-mod-table-body-cell-" + (x + 1);
                _td.className = c_name_cell + " H-mod-table-body-cells " + c_name_body; // 添加类名方便外部修改
                var _td_w = cellWidths[x];
                if(_td_w) _td.style.width = _td_w + "px";
                _td.style.border = "1px solid #ddd";
                _td.style.height = lineHeight + "px";
                _td.style.textAlign = "center";
                if(cfg.addItem){
                    cfg.addItem(_td, lines);
                } else {
                    _td.innerHTML = lines[x] || "-";
                }
                
                _tr.appendChild(_td);
            }
        }
    }

    self.table_head_init = false;
    /** 设置表头数据 */
    if(cfg.thead && cfg.thead.length > 0){
        self.setTHead(cfg.thead);
        self.table_head_init = true;
    }

    /** 设置/重设 数据 */
    self.setData = function(_tbody_data, _thead_data){

        if(_thead_data && _thead_data.length > 0){
            cfg.thead = _thead_data;
            self.setTHead(_thead_data)
        } else if(!self.table_head_init) {
            if(!cfg.thead || cfg.thead.length == 0) return alert("表头不能为空！");
            self.setTHead(cfg.thead);
            self.table_head_init = true;
        }
        
        if(!_tbody_data){
            if(cfg.tbody && cfg.tbody.length > 0){
                _tbody_data = cfg.tbody;
            } else {
                return alert("表数据不能为空！");
            }
        } else {
            cfg.tbody = _tbody_data;
        }
        self.setTBody(_tbody_data);
    }

    return self;
}

var HMOD_XMLHTTP_RET = {
    /** 
     * 请求回调
     * @param {function} callback - 请求完成时执行的回调函数
     * @param {number} callback.code - 状态码
     * @param {string} callback.response - 响应内容
     * @returns {HMOD_XMLHTTP_RET} - 操作结果码
     * */
    call: function(callback){},
    /**
     * 设置请求数据(表单数据格式)
     * @param {JSON} formData json对象
     * @returns {HMOD_XMLHTTP_RET}
     */
    formData: function(formData){},
    /**
     * 设置请求数据(表单数据格式)
     * @param {} formStr json对象
     * @returns {HMOD_XMLHTTP_RET}
     */
    formStr: function(formStr){},
    /**
     * 设置请求数据(Json)
     * @param {string} jsonStr json字符串
     * @returns {HMOD_XMLHTTP_RET}
     */
    jsonStr: function(jsonStr){},
    /**
     * 发送请求
     */
    send: function(){}
}
/**
 * http请求
 * @param {string} _url 请求地址
 * @param {"POST"|"GET"} _method 请求方式
 * @returns {HMOD_XMLHTTP_RET} 返回
 * @example
 * var http = xmlHttp(url, method);          // 初始化
 * http.formData({"id": 1, "type": "yyds"}); // POST请求结构体，表单提交结构，传入Json对象
 * http.formStr("id=1&type=yyds"});          // POST请求结构体，表单提交结构，传入urlencoded字符串
 * http.jsonStr('{"id": 1, "type": "yyds"}');// POST请求结构体，Json提交结构，传入Json字符串
 * http.call(function(code, data){ /TODO/ });// 设置成功回调
 * http.send();                              // 发送请求
 * 
 * // GET
 * var http = xmlHttp("http://127.0.0.1/").call(function(status, response){
 *    // TODO
 * }).send();
 * 
 * // POST
 * var http = xmlHttp("http://127.0.0.1/", "POST").formData({"id": 12138}).call(function(status, response){
 *    // TODO
 * }).send()
 * 
 * // 测试
 * xmlHttp("https://reqres.in/api/users/2").call(function(status, data){
 *      document.body.innerHTML = toJson(data).data.first_name;
 * }).send();
 * xmlHttp("https://jsonplaceholder.typicode.com/posts", "POST").jsonStr('{"title": "Hello World"}')
 *      .call(function (status, data) {
 *          document.body.innerHTML = data;
 *      }).send();
 **/
HMod.xmlHttp = function(_url, _method){

    var http = new ActiveXObject("MSXML2.XMLHTTP");
    /** @type {HMOD_XMLHTTP_RES} */
    var self = {};
    // 请求地址
    var url = _url;
    // 请求方法
    var method = "GET";
    // 结构体
    var body_str = "";
    // 请求头格式
    var content_type = "";
    self.content_type_charset = "; charset=UTF-8";

    if(_method && _method.toLowerCase() == "post"){
        method = "POST";
    } else {
        method = "GET";
    }

    /** 
     * 设置回调
     * @param {function(code, response): void} _callback 回调函数
     * @returns {this}
     * */
    self.call = function(_callback){
        // 监听状态变化
        http.onreadystatechange = function() {
            if(http.readyState == 4) _callback(http.status, http.responseText);
        };
        return self;
    }

    /**
     * 设置请求数据(表单数据格式)
     * @param {} _formData json对象
     * @returns {this}
     */
    self.formData = function(_formData){
        content_type = "application/x-www-form-urlencoded";
        body_str = "";
        var _result = [];
        for (var key in _formData) {
            _result.push(key + "=" + _formData[key]);
        }
        if(_result.length > 0) body_str = _result.join("&");
        return self;
    }
    /**
     * 设置请求数据(表单数据格式)
     * @param {} _formData json对象
     * @returns {this}
     */
    self.formStr = function(_formStr){
        content_type = "application/x-www-form-urlencoded";
        body_str = _formStr;
        return self;
    }

    /**
     * 设置请求数据(Json)
     * @param {} _jsonStr json字符串
     * @returns {this}
     */
    self.jsonStr = function(_jsonStr){
        content_type = "application/json";
        body_str = _jsonStr;
        return self;
    }

    /**
     * 发送请求
     */
    self.send = function(){
        http.open(method, url, true);
        if(method == "POST") {
            http.setRequestHeader("Content-Type", content_type + self.content_type_charset);
        } else {
            body_str = undefined;
        }
        http.send(body_str);
    }

    return self;
}

/**
 * 读取文件
 * @param filePath 文件路径
 * @returns {string} 文件内容
 * @example
 * var content = readFile("./test.txt");
 * alert(content);
 */
HMod.readFile = function(filePath, stream) {
    var result = "";
    try {
        if (!stream) {
            stream = new ActiveXObject("ADODB.Stream");
            stream.Type = 2; // 文本类型
            stream.Charset = "utf-8";
            stream.Open();
        }
        var fso = new ActiveXObject("Scripting.FileSystemObject");
        if (fso.FileExists(filePath)) {// 检查文件是否存在
            stream.LoadFromFile(filePath);// 加载现有内容
            result = stream.ReadText(-1); // 读取全部内容
        }
    } catch (error) { }
    return result;
}

/**
 * 写入文件
 * @param filePath 文件路径
 * @param content 文件内容
 * @param append 是否追加模式
 * @returns {boolean} 是否成功
 */
HMod.writeFile = function(filePath, content, append) {
    try {
        var stream = new ActiveXObject("ADODB.Stream");
        stream.Type = 2; // 文本类型
        stream.Charset = "utf-8";
        stream.Open();

        // 是否是追加模式
        if(append) HMod.readFile(filePath, stream); // 追加 先读取原有内容

        // 写入内容
        stream.WriteText(content);

        // 保存并关闭
        stream.SaveToFile(filePath, 2); // 覆盖原文件
        stream.Close();

        return true;
    } catch (error) {
        alert(error.message);
        return false;
    }
}

/**
 * 获取时间变量
 * @param {string} separator 分隔符
 * @returns {string} 
 */
HMod.timeVar = function(separator, date) {
    separator = separator || "";
    date = date || new Date();
    var year = date.getFullYear();
    var month = date.getMonth() + 1;
    var day = date.getDate();
    
    return year + separator + 
           (month < 10 ? '0' + month : month) + separator + 
           (day < 10 ? '0' + day : day);
}


/**
 * 字符串转Json，捕捉异常使其不报错
 **/
HMod.toJsonTC = function(json_str){
    try {
        return eval("(" + json_str + ")");
    } catch (e) {
        return false;
    }
}
/** 
 * 字符串转Json
 **/
HMod.toJson = function(json_str){
    return eval("(" + json_str + ")");
}

/**
 * 清空元素下所有子元素
 * @param element 要清空的元素
 */
HMod.clearElement = function (element) {
    while (element.firstChild) {
        element.removeChild(element.firstChild);
    }
}

var shell = new ActiveXObject('WScript.Shell');
/**
 * 同时执行一条或多条cmd命令,注意，这里的多条只能是每条都有返回结果，如果没有返回结果它就不会继续执行
 * 在参数最后可以指定boolean参数，表示是否显示cmd窗，默认不显示
 */
function cmd() {
    // 有点BUG
    var args = arguments;
    var cmd_str = "";
    var len = args.length;
    var is_show = false;
    if (args.length > 1) {
        for (var _i = 0; _i < len - 1; _i++) {
            cmd_str += args[_i];
            if (_i < args.length - 2) cmd_str += "&&";
        }
        if (typeof args[len - 1] == "boolean") {
            is_show = args[len - 1];
        } else cmd_str += "&&" + args[len - 1];
    } else if (args.length == 1) {
        cmd_str = args[0];
    } else {
        return false;
    }
    return shell.run('cmd.exe /c ' + cmd_str, is_show ? 1 : 0, true) == 0 ? true : false;
}

/** 格式化字符串 */
String.prototype.format = function () {
    var args = arguments;
    var result = this;
    for (var _idx = 0; _idx < args.length; _idx++) {
        result = result.replace("%s", args[_idx]);
    }
    return result;
}
/*********************************/
/*

// 强制使用最新模式
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv="X-UA-Compatible" content="IE=9"> 

// 设置程序左上角图标
<hta:application icon="./icon.ico"/>
// 设置程序名称
<hta:application applicationname="HTA-oiaKJUHr54sIDH"/>
// 单例模式，就是说只能打开一个窗口，需要设置applicationname有效
<hta:application singleinstance="yes"/>

*/